/**********************************************************************************\
** 文件名称: main_user.c
** 创建人员: YCG
** 创建日期: 2018-12-20
** 文档描述:
** 版本代号: V0.1
** 版本说明: 初始版本
\********************************************************************************/

#include "main_user.h"
#include "numctrl.h"

#include "buf.h"
#include "uart.h"
#include "systime.h"

#include "list.h"
#include "Servo1.h"
#include "RGB.h"
#include "key.h"
#include "VS1838.h"
#include "Motor.h"
#include "HCSR04.h"
#include "beep.h"
#include "track.h"

#include "cmd.h"

void IR1CallBack(IR_struct * IR);

const uint8_t LED_Speed[8] = {3, 5, 10, 15, 20, 40, 80, 160};
const uint8_t LED_Light[8] = {2, 5, 10, 20, 50, 80, 150, 250};

numctrl_t Mode[1];             //系统的运行模式

numctrl_t NumMotorSpeed[1];    //电机速度控制量

numctrl_t NumBEEP[1];          //蜂鸣器播放控制量

numctrl_t NumLEDMode[1];       //LED模式控制量
numctrl_t NumLEDLight[1];       //LED亮度控制量
numctrl_t NumLEDSpeed[1];       //LED速度控制量

uint32_t TrackTime = 0;

void main_user(void) {

    USART_Config(1500000);        //串口配置
    KeyInit();                    //按键初始化
    IrInit(&IR1, IR_GPIO_Port, IR_Pin, IR1CallBack);   //红外遥控初始化

    SystimeStart();       //系统定时器启动，全局计时
    MoterInit(10000);     //电机初始化
    RGB_Init(4);        //LED灯初始化
    HCSR04Init();       //超声波模块初始化
    BeepInit();          //蜂鸣器初始化
    ServoInit();
	
    BeepPlay(1);      //提示系统启动
    ServoAdd(0,SER_GPIO_Port, SER_Pin);
    ServoSet(0,90);
	
    NumInit(Mode, 1, 1, 3);                             //初始化系统模式控制 步距-最小值-最大值

    NumInit(NumMotorSpeed, 10, 0, 100);                 //初始化电机速度控制 步距-最小值-最大值

    NumInit(NumLEDMode, 1, RGB_CLOSE, RGB_RAINBOW_AVR); //初始化LED模式控制 步距-最小值-最大值
    NumInit(NumLEDLight, 1, 0, 7);                      //初始化LED亮度控制 步距-最小值-最大值
    NumInit(NumLEDSpeed, 1, 0, 4);                      //初始化LED速度控制 步距-最小值-最大值

    NumInit(NumBEEP, 1, BEEP_B3, BEEP_TIG);             //初始化蜂鸣器控制 步距-最小值-最大值
		
    NumInit(HCNum, 4, 2, 30);                           //初始化距离控制 步距-最小值-最大值

    NumSet(Mode, 3);    //设置初始速度
		
    NumSet(NumMotorSpeed, 5);    //设置初始速度
    NumSet(NumLEDMode, RGB_RAINBOW_AVR);   //设置LED的初始模式
    NumSet(NumLEDLight, 2);    //设置灯的初始亮度
    NumSet(NumLEDSpeed, 2);    //设置灯的初始速度

    NumSet(HCNum, 8);          //设置超声波模块的初始感应距离

    RGB_Set(NumLEDMode->num,  LED_Light[NumLEDLight->num], LED_Speed[NumLEDSpeed->num]);  //更新LED灯的显示

    while(1) {
        switch (Mode->num)   //判断当前的系统模式
        {
        case 1:             //自动避障模式
            if(ReadDistance() < HCNum->num) {
                BeepPlay(0);
                SpeedCtrl(-NumMotorSpeed->num, -NumMotorSpeed->num, 300, MOTOR_HIGH_PRI);
                DelayMs(200);
                if(GetSystimeMs() & 0x4000) {     //每隔这么久改变一次旋转的方向
                    SpeedCtrl(30, -30, 500, MOTOR_HIGH_PRI);
                } else {
                    SpeedCtrl(-30, 30, 500, MOTOR_HIGH_PRI);
                }
            } else {
                SpeedCtrl(NumMotorSpeed->num, NumMotorSpeed->num, 10, MOTOR_LOW_PRI);
                DelayMs(5);
            }
            if(Mode->num != 0) {
                SpeedCtrl(0, 0, 10000, MOTOR_LOW_PRI);
            }
            break;

        case 2:            //循迹模式
            switch (GetTrack())
            {
            case 0:
                Uprintf("直行\r\n");
                SpeedCtrl(NumMotorSpeed->num, NumMotorSpeed->num, 10, MOTOR_LOW_PRI);
                break;
            case 1:
                Uprintf("右转\r\n");
                SpeedCtrl(NumMotorSpeed->num, 0, 5, MOTOR_HIGH_PRI);
                break;
            case 2:
                Uprintf("左转\r\n");
                SpeedCtrl( 0, NumMotorSpeed->num, 5, MOTOR_HIGH_PRI);
                break;
            case 3:
                TrackTime = GetSystimeMs();

                Uprintf("TrackTime1:%d\r\n", TrackTime);
                while(GetTrack() == 0x03) {
                    SpeedCtrl(4, 4, 10, MOTOR_LOW_PRI);
                    DelayMs(10);
                }
                Uprintf("TrackTime2:%d\r\n", GetSystimeMs());

                if(GetSystimeMs() - TrackTime > 100) {
                    SpeedCtrl(50, -50, 900, MOTOR_HIGH_PRI);
                    DelayMs(900);
                }
                break;
            }
            DelayMs(5);
            break;
        default:    //遥控模式
            break;
        }
        //   Uprintf("距离为:%d\r\n", ReadDistance());
    }
}

/*******************************************************************************
** 函数名称: CmdSendCallBack
** 功能描述: 每次发送完系统指令后，处理需要实时处理的系统指令
** 参数说明: None
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-22
********************************************************************************/
void CmdSendCallBack(void) {
    static uint8_t CmdNumReceiver = CMD_MOTOR_SPEED;    //保留数据的接收者，供数字设置模式使用，意味着数字键盘为哪种模式所用
    static uint8_t MotorLastState = MOTOR_CTRL_STOP;     //保留上一次的方向

    uint8_t dat = 0;
  //  Uprintf("CmdSendCallBack\r\n");

    /*****************接收数字处理******************/
    if(GetCmd(CMD_NUM)) {     //数字信息
        dat = GetCmdDat(CMD_NUM) | CMD_DAT; //获取数字信息，数据范围为0-127，最高位无效
        SendCmdDat(CmdNumReceiver, dat);   //发送数据给指定的命令
    }

    /*****************系统运行模式处理******************/
    if(GetCmd(CMD_SYS_MODE)) {   //系统模式设置
        CmdNumReceiver = CMD_SYS_MODE;   //获取数字键盘的设置权限
        dat = GetCmdDat(CMD_SYS_MODE); //获取数据或者具体的命令
        switch(dat) {   //判断是什么类型
        case CMD_NO:     //单纯的命令，不携带具体信息
            NumSet(Mode, 3);
            break;
        case CMD_ADD:    //增加命令
            NumAdd(Mode);
            break;
        case CMD_DEC:    //减小命令
            NumDec(Mode);
            break;
        default:      //未知命令，包括数字信息
            if(dat & CMD_DAT) {  //数字信息
                NumSet(Mode, dat & CMD_DAT_MASK);  //根据数字信息设置模式
            }
            break;
        }
    }
    /*****************电机速度控制处理******************/
    if(GetCmd(CMD_MOTOR_SPEED)) {
        dat = GetCmdDat(CMD_MOTOR_SPEED);
        switch(dat) {
        case CMD_NO:
            NumSet(NumMotorSpeed, 0);
            break;
        case CMD_ADD:
            NumAdd(NumMotorSpeed);
            break;
        case CMD_DEC:
            NumDec(NumMotorSpeed);
            break;
        default:
            if(dat & CMD_DAT) {
                NumSet(NumMotorSpeed, (dat & CMD_DAT_MASK) * 6);
                if(Mode->num == 0||Mode->num==Mode->max) {
                SendCmdDat(CMD_MOTOR_CTRL, MotorLastState);   //立刻刷新速度
                }
            }
            break;
        }
    }

    /*****************遥控模式方向控制******************/
    if(GetCmd(CMD_MOTOR_CTRL)) {
        CmdNumReceiver = CMD_MOTOR_SPEED;   //获取数字键盘的设置权限
        MotorLastState = GetCmdDat(CMD_MOTOR_CTRL);	 //保留这一次的方向，供调速使用
        switch(MotorLastState) {
        case MOTOR_CTRL_STOP:
            SpeedCtrl(0, 0, 10000, MOTOR_LOW_PRI);
            break;
        case MOTOR_CTRL_UP:
            SpeedCtrl(NumMotorSpeed->num, NumMotorSpeed->num, 10000, MOTOR_LOW_PRI);
            break;
        case MOTOR_CTRL_DOWN:
            SpeedCtrl(-NumMotorSpeed->num, -NumMotorSpeed->num, 10000, MOTOR_LOW_PRI);
            break;
        case MOTOR_CTRL_LEFT:
            SpeedCtrl(-NumMotorSpeed->num, NumMotorSpeed->num, 10000, MOTOR_LOW_PRI);
            break;
        case MOTOR_CTRL_RIGHT:
            SpeedCtrl(NumMotorSpeed->num, -NumMotorSpeed->num, 10000, MOTOR_LOW_PRI);
            break;
        }
    }

    /*****************LED运行模式控制******************/
    if(GetCmd(CMD_LED_MODE)) {
        CmdNumReceiver = CMD_LED_MODE;   //获取数字键盘的设置权限
        dat = GetCmdDat(CMD_LED_MODE);
        switch(dat) {
        case CMD_NO:
            // NumSet(NumLEDMode, 0);
            break;
        case CMD_ADD:
            NumAdd(NumLEDMode);
            break;
        case CMD_DEC:
            NumDec(NumLEDMode);
            break;
        default:
            if(dat & CMD_DAT) {
                NumSet(NumLEDMode, dat & CMD_DAT_MASK);
            }
            break;
        }
        RGB_Set(NumLEDMode->num,  LED_Light[NumLEDLight->num], LED_Speed[NumLEDSpeed->num]);
    }

    /*****************LED亮度控制******************/
    if(GetCmd(CMD_LED_LIGHT)) {
        CmdNumReceiver = CMD_LED_LIGHT;   //获取数字键盘的设置权限
        dat = GetCmdDat(CMD_LED_LIGHT);
        switch(dat) {
        case CMD_NO:
            NumSet(NumLEDLight, 0);
            break;
        case CMD_ADD:
            NumAdd(NumLEDLight);
            break;
        case CMD_DEC:
            NumDec(NumLEDLight);
            break;
        default:
            if(dat & CMD_DAT) {
                NumSet(NumLEDLight, dat & CMD_DAT_MASK);
            }
            break;
        }
        RGB_Set(NumLEDMode->num,  LED_Light[NumLEDLight->num], LED_Speed[NumLEDSpeed->num]);
    }
    /*****************LED速度控制******************/
    if(GetCmd(CMD_LED_SPEED)) {
        CmdNumReceiver = CMD_LED_SPEED;   //获取数字键盘的设置权限
        dat = GetCmdDat(CMD_LED_SPEED);
        switch(dat) {
        case CMD_NO:
            NumSet(NumLEDSpeed, 0);
            break;
        case CMD_ADD:
            NumAdd(NumLEDSpeed);
            break;
        case CMD_DEC:
            NumDec(NumLEDSpeed);
            break;
        default:
            if(dat & CMD_DAT) {
                NumSet(NumLEDSpeed, dat & CMD_DAT_MASK);
            }
            break;
        }
        RGB_Set(NumLEDMode->num,  LED_Light[NumLEDLight->num], LED_Speed[NumLEDSpeed->num]);
    }

    /*****************蜂鸣器控制******************/
    if(GetCmd(CMD_BEEP_PLAY)) {
        CmdNumReceiver = CMD_BEEP_PLAY;   //获取数字键盘的设置权限
        dat = GetCmdDat(CMD_BEEP_PLAY);
        switch(dat) {
        case CMD_NO:
            NumSet(NumBEEP, 0);
            break;
        case CMD_ADD:
            NumAdd(NumBEEP);
            break;
        case CMD_DEC:
            NumDec(NumBEEP);
            break;
        default:
            if(dat & CMD_DAT) {
                NumSet(NumBEEP, dat & CMD_DAT_MASK);
            }
            break;
        }
        BeepPlay(NumBEEP->num);
    }
		    /*****************距离控制******************/
    if(GetCmd(CMD_HC_LIMIT)) {
        CmdNumReceiver = CMD_HC_LIMIT;   //获取数字键盘的设置权限
        dat = GetCmdDat(CMD_HC_LIMIT);
        switch(dat) {
        case CMD_NO:
//            NumSet(HCNum, 0);
            break;
        case CMD_ADD:
            NumAdd(HCNum);
            break;
        case CMD_DEC:
            NumDec(HCNum);
            break;
        default:
            if(dat & CMD_DAT) {
                NumSet(HCNum, (dat & CMD_DAT_MASK)*3);
            }
            break;
        }
    }
}

/*******************************************************************************
** 函数名称: KeyCallback
** 功能描述: 每次检测到按键按下之后都会执行这里
** 参数说明: None
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-22
********************************************************************************/
void KeyCallback(void) {
    BeepPlay(BEEP_D2);
    if(KeyRead(KEY1, KEY_SHORT)) {
        SendCmdDat(CMD_SYS_MODE, CMD_DEC);
    }
    if(KeyRead(KEY1, KEY_LONG)) {
        SendCmdDat(CMD_SYS_MODE, CMD_ADD);
    }

    if(KeyRead(KEY2, KEY_SHORT)) {
       SendCmdDat(CMD_MOTOR_SPEED, CMD_DEC);
    }  
		if(KeyRead(KEY2, KEY_LONG)) {
        SendCmdDat(CMD_MOTOR_SPEED, CMD_ADD);
    }

    if(KeyRead(KEY3, KEY_SHORT)) {
        SendCmdDat(CMD_BEEP_PLAY, CMD_DEC);
    }
		if(KeyRead(KEY3, KEY_LONG)) {
        SendCmdDat(CMD_BEEP_PLAY, CMD_ADD);
    }
		
    if(KeyRead(KEY4, KEY_SHORT)) {
        SendCmdDat(CMD_LED_LIGHT, CMD_DEC);
    }		
    if(KeyRead(KEY4, KEY_LONG)) {
        SendCmdDat(CMD_LED_LIGHT, CMD_ADD);
    }
}

/*******************************************************************************
** 函数名称: IR1CallBack
** 功能描述: 每次红外遥控接收到数据以后会执行这里
** 参数说明: IR: [输入/出]
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-22
********************************************************************************/
void IR1CallBack(IR_struct * IR) {

    Uprintf("类型%d:%s\r\n", IR->Code->type, IR->Code->name);
    Uprintf("地址:0x%02x\r\n", IR->add);
    Uprintf("数据:0x%02x\r\n", IR->dat);
    BeepPlay(BEEP_D1);
    //if(IR->Code->type == IR_KANGJIA)
    switch(IR->dat) {

    case 0x00:  //开关,恢复为遥控模式
        SendCmdDat(CMD_SYS_MODE, CMD_NO);
        break;

    case 0xd0 :   //切换到下一个模式
        SendCmdDat(CMD_SYS_MODE, CMD_ADD);
        break;

    case 0xa0:  //中
        SendCmdDat(CMD_MOTOR_CTRL, MOTOR_CTRL_STOP);
        break;

    case 0xc0:  //上
        SendCmdDat(CMD_MOTOR_CTRL, MOTOR_CTRL_UP);
        break;

    case 0x20:  //下
        SendCmdDat(CMD_MOTOR_CTRL, MOTOR_CTRL_DOWN);
        break;

    case 0x80:  //左
        SendCmdDat(CMD_MOTOR_CTRL, MOTOR_CTRL_LEFT);
        break;

    case 0x40:  //右
        SendCmdDat(CMD_MOTOR_CTRL, MOTOR_CTRL_RIGHT);
        break;
		
			
    case 0x90: 	
 SendCmdDat(CMD_MOTOR_SPEED, CMD_ADD);
		   break;		
		
    case 0x50: 	
 SendCmdDat(CMD_MOTOR_SPEED, CMD_DEC);
		   break;
		
		
    case 0x60:  //LED亮度增加
        SendCmdDat(CMD_LED_LIGHT, CMD_ADD);
        break;

    case 0xe0:  //LED速度增加
        SendCmdDat(CMD_LED_SPEED, CMD_ADD);
        break;

    case 0x10:  //蜂鸣器
        SendCmdDat(CMD_HC_LIMIT, CMD_ADD);
        break;

  
    }
}
/********************************End of File************************************/
